import { markRaw } from 'vue';
import { acceptHMRUpdate, defineStore } from 'pinia';
import { RouterView } from 'vue-router';
import type { RouteRecordRaw } from 'vue-router';
import { getUserMenuAuthApi } from '@/api';
import type { MenuRecordRaw, ComponentRecordType } from '@/types';
import type { UserMenuAuth } from './type';
import { Layout } from '@/layouts';

type AccessToken = null | string;

const modules: ComponentRecordType = import.meta.glob('/src/views/**/**.vue'); // 匹配菜单路由
// 获取组件地址
function getComponent(componentName: string) {
  let component = null;
  switch (componentName) {
    case 'Layout': {
      component = markRaw(Layout);
      break;
    }
    case 'RouterView': {
      component = markRaw(RouterView);
      break;
    }
    default: {
      component = modules[`/src/views${componentName}.vue`];
      break;
    }
  }
  return component;
}
function treeToRoutes(list: UserMenuAuth[]): RouteRecordRaw[] {
  return list.map((item: UserMenuAuth) => {
    return {
      meta: {
        icon: item.icon,
        title: item.title,
      },
      path: item.path,
      name: item.routeName,
      component: getComponent(item.component),
      children: item.children ? treeToRoutes(item.children) : [],
    };
  });
}
function getAccessMenus(
  menuList: any,
  paths: string[] = [],
  path: string = '',
) {
  const sortList = menuList.sort(
    (a: UserMenuAuth, b: UserMenuAuth) => a.sort - b.sort,
  );

  return sortList.map((menuItem: any) => {
    const {
      meta,
      title,
      icon,
      redirect,
      children,
      sort,
      path: menuPath,
    } = menuItem;
    const {
      activeIcon,
      badge,
      badgeType,
      badgeVariants,
      hideChildrenInMenu = false,
      link,
    } = meta || {};

    const newPath = path + (path ? '/' : '') + menuPath;
    const newPaths = [...paths, newPath];
    const resultPath = hideChildrenInMenu ? redirect || path : link || newPath;

    return {
      activeIcon,
      badge,
      badgeType,
      badgeVariants,
      icon,
      name: title || '',
      order: sort,
      parent: path || undefined,
      parents: paths.length > 0 ? [...paths] : undefined,
      path: resultPath as string,
      show: !menuItem?.meta?.hideInMenu,
      children:
        children?.length > 0
          ? getAccessMenus(menuItem.children, newPaths, newPath)
          : [],
    };
  });
}

interface AccessState {
  /**
   * 有权限的菜单列表
   */
  accessMenus: MenuRecordRaw[];
  /**
   * 有权限的路由列表
   */
  accessRoutes: RouteRecordRaw[];
  /**
   * 有权限的按钮列表
   */
  accessPerms: Recordable<string[]>;
  /**
   * token
   */
  accessToken: AccessToken;
  /**
   * 是否已经检查过权限
   */
  isAccessChecked: boolean;
  /**
   * 登录是否过期
   */
  loginExpired: boolean;
}

export const useAccessStore = defineStore('accessStore', {
  state: (): AccessState => ({
    accessMenus: [],
    accessRoutes: [],
    accessPerms: {},
    accessToken: null,
    isAccessChecked: false,
    loginExpired: false,
  }),
  persist: {
    // 持久化
    pick: ['accessToken'],
  },
  actions: {
    setAccessToken(token: AccessToken) {
      this.accessToken = token;
    },
    setIsAccessChecked(isAccessChecked: boolean) {
      this.isAccessChecked = isAccessChecked;
    },
    setAccessRoutes(routes: RouteRecordRaw[]) {
      this.accessRoutes = routes;
    },
    setAccessMenus(menus: MenuRecordRaw[]) {
      this.accessMenus = menus;
    },
    setAccessPerms(perms: Recordable<string[]>) {
      this.accessPerms = perms;
    },
    setLoginExpired(loginExpired: boolean) {
      this.loginExpired = loginExpired;
    },
    async generateRoutesByBackend() {
      try {
        const { menu, btnPerms } = await getUserMenuAuthApi();
        this.setAccessRoutes(treeToRoutes(menu ?? []));
        this.setAccessMenus([
          {
            activeIcon: undefined,
            badge: undefined,
            badgeType: 'dot',
            badgeVariants: undefined,
            children: [],
            icon: 'mdi:view-dashboard-outline',
            name: 'menu.dashboard',
            order: 0,
            parent: undefined,
            parents: undefined,
            path: '/dashboard',
            show: true,
          },
          ...getAccessMenus(menu, [], ''),
        ]);
        this.setAccessPerms(btnPerms ?? {});
      } catch (error) {
        console.log(error);
      }
    },
  },
});

// 解决热更新问题
const hot = import.meta.hot;
if (hot) {
  hot.accept(acceptHMRUpdate(useAccessStore, hot));
}
